package com.yxx.config;

import com.yxx.config.properties.ThreadPoolProperties;
import com.yxx.utils.ThreadUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.Resource;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 * @author yuxiangxun
 * @date 2025/1/18
 * @apiNote
 */
@Configuration
public class ThreadPoolConfig {

    @Resource
    private ThreadPoolProperties threadPoolProperties;

    /**
     * 创建ThreadPoolTaskExecutor线程池
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程池大小
        executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
        // 最大可创建的核心线程数
        executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
        // 等待队列最大长度
        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
        // 线程池维护线程所允许的空闲时间
        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
        // 线程池对拒绝任务（无线程可用）的处理策略  当线程无法接收新任务时， CallerRunsPolicy策略将会交给 调用者线程（提交任务的线程）处理该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    /**
     * 创建scheduledExecutorService线程池
     * 执行周期性或定时任务
     * @return
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService() {
        // 核心线程数
        // 线程工厂 设置线程命名模式和守护线程属性
        // 拒绝策略
        return new ScheduledThreadPoolExecutor(
                threadPoolProperties.getCorePoolSize(),
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
                new ThreadPoolExecutor.CallerRunsPolicy()){
            // 重写钩子方法，任务执行后的清理或日志记录
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                // 调用 父类ThreadPoolExecutor 的 afterExecute 方法 确保父类的逻辑正常执行
                super.afterExecute(r, t);
                // 打印异常信息
                ThreadUtils.printException(r, t);
            }
        };
    }
}
